{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "d81a94f6-1c49-45c4-96b3-192fae2d75ff",
   "metadata": {},
   "source": [
    "# 机器学习基础\n",
    "- 数据集的划分\n",
    "- 数据集接口介绍"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dfdf9690-629f-416c-af30-1dc6d88b7399",
   "metadata": {},
   "source": [
    "## 数据集的划分\n",
    "- 前提:机器学习就是从数据中自动分析出规律,并利用对未知数据进行预测.换句话说,我们的模型一定是要经过样本数据对其进行训练,才可以对未知数据进行预测的\n",
    "- 问题:我们得到数据后,是否将数据全部用来训练模型\n",
    "  - 答案是否的,如果模型对原先的数据进行预测,由于模型(数据的规律)本来就是从该数据中获取的,所以预测的精度几乎会是百分百.所以想要评估数据的好坏,需要使用一组新数据对模型进行评估.\n",
    "  - 因此我们需要将原先的样本数据拆分成两个部分(二八分):\n",
    "    - 训练集:训练模型(八)\n",
    "    - 测试集:测试模型(二)\n",
    "      - 不同类型的模型对应的评估方式是不一样的\n",
    "- 数据划分的API:\n",
    "  - from sklearn.model_select import train_test_split\n",
    "  - train_test_split(x,y,test_size,random_state)\n",
    "    - 参数介绍:\n",
    "    - x:特征\n",
    "    - y:目标\n",
    "    - test_size:测试集的比例\n",
    "    - random_state:打乱的随机种子\n",
    "  - 返回值:训练特质, 测试特征,训练特征,测试目标"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c78242a7-7c9a-41d8-942c-05728d81eb42",
   "metadata": {},
   "source": [
    "## 数据集接口介绍\n",
    "- sklearn.datasets.load_*():获取小规模的数据集\n",
    "- sklearn.datasets.fetch_*(data_home=None,subset):获取大规模的数据集\n",
    "    - data_home:表示数据集下载目录,None为默认值表示的是家目录/scikit_learn_data(自动创建该文件夹)下.\n",
    "    - 需要从网络下载.subset为需要下载的数据集,可以为:train,test,all"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "78863cca-0493-47db-92f7-695f11729245",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'data': array([[1.423e+01, 1.710e+00, 2.430e+00, ..., 1.040e+00, 3.920e+00,\n",
      "        1.065e+03],\n",
      "       [1.320e+01, 1.780e+00, 2.140e+00, ..., 1.050e+00, 3.400e+00,\n",
      "        1.050e+03],\n",
      "       [1.316e+01, 2.360e+00, 2.670e+00, ..., 1.030e+00, 3.170e+00,\n",
      "        1.185e+03],\n",
      "       ...,\n",
      "       [1.327e+01, 4.280e+00, 2.260e+00, ..., 5.900e-01, 1.560e+00,\n",
      "        8.350e+02],\n",
      "       [1.317e+01, 2.590e+00, 2.370e+00, ..., 6.000e-01, 1.620e+00,\n",
      "        8.400e+02],\n",
      "       [1.413e+01, 4.100e+00, 2.740e+00, ..., 6.100e-01, 1.600e+00,\n",
      "        5.600e+02]]), 'target': array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
      "       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
      "       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1,\n",
      "       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n",
      "       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n",
      "       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2,\n",
      "       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\n",
      "       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\n",
      "       2, 2]), 'frame': None, 'target_names': array(['class_0', 'class_1', 'class_2'], dtype='<U7'), 'DESCR': '.. _wine_dataset:\\n\\nWine recognition dataset\\n------------------------\\n\\n**Data Set Characteristics:**\\n\\n:Number of Instances: 178\\n:Number of Attributes: 13 numeric, predictive attributes and the class\\n:Attribute Information:\\n    - Alcohol\\n    - Malic acid\\n    - Ash\\n    - Alcalinity of ash\\n    - Magnesium\\n    - Total phenols\\n    - Flavanoids\\n    - Nonflavanoid phenols\\n    - Proanthocyanins\\n    - Color intensity\\n    - Hue\\n    - OD280/OD315 of diluted wines\\n    - Proline\\n    - class:\\n        - class_0\\n        - class_1\\n        - class_2\\n\\n:Summary Statistics:\\n\\n============================= ==== ===== ======= =====\\n                                Min   Max   Mean     SD\\n============================= ==== ===== ======= =====\\nAlcohol:                      11.0  14.8    13.0   0.8\\nMalic Acid:                   0.74  5.80    2.34  1.12\\nAsh:                          1.36  3.23    2.36  0.27\\nAlcalinity of Ash:            10.6  30.0    19.5   3.3\\nMagnesium:                    70.0 162.0    99.7  14.3\\nTotal Phenols:                0.98  3.88    2.29  0.63\\nFlavanoids:                   0.34  5.08    2.03  1.00\\nNonflavanoid Phenols:         0.13  0.66    0.36  0.12\\nProanthocyanins:              0.41  3.58    1.59  0.57\\nColour Intensity:              1.3  13.0     5.1   2.3\\nHue:                          0.48  1.71    0.96  0.23\\nOD280/OD315 of diluted wines: 1.27  4.00    2.61  0.71\\nProline:                       278  1680     746   315\\n============================= ==== ===== ======= =====\\n\\n:Missing Attribute Values: None\\n:Class Distribution: class_0 (59), class_1 (71), class_2 (48)\\n:Creator: R.A. Fisher\\n:Donor: Michael Marshall (MARSHALL%PLU@io.arc.nasa.gov)\\n:Date: July, 1988\\n\\nThis is a copy of UCI ML Wine recognition datasets.\\nhttps://archive.ics.uci.edu/ml/machine-learning-databases/wine/wine.data\\n\\nThe data is the results of a chemical analysis of wines grown in the same\\nregion in Italy by three different cultivators. There are thirteen different\\nmeasurements taken for different constituents found in the three types of\\nwine.\\n\\nOriginal Owners:\\n\\nForina, M. et al, PARVUS -\\nAn Extendible Package for Data Exploration, Classification and Correlation.\\nInstitute of Pharmaceutical and Food Analysis and Technologies,\\nVia Brigata Salerno, 16147 Genoa, Italy.\\n\\nCitation:\\n\\nLichman, M. (2013). UCI Machine Learning Repository\\n[https://archive.ics.uci.edu/ml]. Irvine, CA: University of California,\\nSchool of Information and Computer Science.\\n\\n.. dropdown:: References\\n\\n    (1) S. Aeberhard, D. Coomans and O. de Vel,\\n    Comparison of Classifiers in High Dimensional Settings,\\n    Tech. Rep. no. 92-02, (1992), Dept. of Computer Science and Dept. of\\n    Mathematics and Statistics, James Cook University of North Queensland.\\n    (Also submitted to Technometrics).\\n\\n    The data was used with many others for comparing various\\n    classifiers. The classes are separable, though only RDA\\n    has achieved 100% correct classification.\\n    (RDA : 100%, QDA 99.4%, LDA 98.9%, 1NN 96.1% (z-transformed data))\\n    (All results using the leave-one-out technique)\\n\\n    (2) S. Aeberhard, D. Coomans and O. de Vel,\\n    \"THE CLASSIFICATION PERFORMANCE OF RDA\"\\n    Tech. Rep. no. 92-01, (1992), Dept. of Computer Science and Dept. of\\n    Mathematics and Statistics, James Cook University of North Queensland.\\n    (Also submitted to Journal of Chemometrics).\\n', 'feature_names': ['alcohol', 'malic_acid', 'ash', 'alcalinity_of_ash', 'magnesium', 'total_phenols', 'flavanoids', 'nonflavanoid_phenols', 'proanthocyanins', 'color_intensity', 'hue', 'od280/od315_of_diluted_wines', 'proline']}\n"
     ]
    }
   ],
   "source": [
    "# 获取小规模数据集\n",
    "import sklearn.datasets as datasets\n",
    "data = datasets.load_wine()\n",
    "print(data)\n",
    "# 提取特征数据和标签数据\n",
    "feature = data['data']\n",
    "target = data['target'] "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "f9a018c8-e23b-4af4-87eb-584d16a885ce",
   "metadata": {},
   "outputs": [],
   "source": [
    "feature.shape,target.shape\n",
    "\n",
    "# 将target变形成二维的\n",
    "target=target.reshape((178,1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "0e642a3a-2877-442f-be7e-a3f6f0cbe7b1",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "08849fbc-5fe1-4cbf-b572-29b9ddda1fef",
   "metadata": {},
   "outputs": [],
   "source": [
    "result = np.concatenate((feature,target),axis=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "bbea12f6-c394-4ce9-aa00-628521025e52",
   "metadata": {},
   "outputs": [],
   "source": [
    "df = pd.DataFrame(data=result)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "dae36370-4c13-4382-8b7f-2ae6af9198bb",
   "metadata": {},
   "outputs": [],
   "source": [
    "import requests\n",
    "proxies={'http':'http://user:'}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "097465ec-f2bb-4bab-a1ab-9e9c7fbb4e96",
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "# 返回大规模数据集\n",
    "# data_home:将数据存储到哪个位置\n",
    "# subset:下载哪些数据集,all(所有数据集),tranin(训练集),test(测试集)\n",
    "# random_state:\n",
    "# datasets.fetch_20newsgroups(data_home='./data',subset='test')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "c6b992b4-9227-4bc2-9459-ef96fde91023",
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "# 如何切分数据集\n",
    "from sklearn.model_selection import train_test_split\n",
    "iris = datasets.load_iris()\n",
    "feature = iris['data']\n",
    "target = iris['target']\n",
    "\n",
    "# test_size:表示测试集占百分之多少\n",
    "# random_state=x:是否打乱,x为随机种子\n",
    "\n",
    "# x_train:训练集的特征数据\n",
    "# x_test:测试集的特征数据\n",
    "# y_train:训练集的标签数据\n",
    "# y_test:测试集的标签数据\n",
    "x_train,x_test,y_train,y_test=train_test_split(feature,target,test_size=0.2,random_state=2021)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bcb3fde8-dd22-48c2-b517-eccdf3b2c0de",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "10516fce-d53c-4cb4-b6aa-e71f3047c904",
   "metadata": {},
   "source": [
    "# 模型的保存与加载\n",
    "- 方式1:\n",
    "  - from sklearrn.externals import joblib\n",
    "  - joblib.dump(model.'xxxm'):保存\n",
    "  - joblib.load('xxx.m'):加载"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dcea0e49-8b75-4790-89ad-85a1b5d0825f",
   "metadata": {},
   "source": [
    "- 方式2:\n",
    "  - import pickle\n",
    "  - with open('./123.pkl','wb') as fp:\n",
    "    - pickle.dump(linner,fp)\n",
    "  - with open('./123.pkl','rb') as fp:\n",
    "    - linner=pickle.load(fp)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "56efcf09-22be-4a28-8f3c-9d3f448c596a",
   "metadata": {},
   "source": [
    "- 需求:\n",
    "  - 获取基于datasets获取一组样本数据\n",
    "  - 对样本数据进行切分\n",
    "  - 对训练集数据进行归一化处理\n",
    "  - 使用测试数据测试模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "382c7a2b-5fe7-4dd0-8e1e-cb444cfd5b43",
   "metadata": {},
   "outputs": [],
   "source": [
    "iris = datasets.load_iris()\n",
    "# 提取特征数据和标签数据\n",
    "feature = iris['data']\n",
    "target = iris.get('target')\n",
    "\n",
    "# 切分数据\n",
    "x_train,x_test,y_train,y_test=train_test_split(feature,target,test_size=0.2,random_state=2021)\n",
    "\n",
    "# 训练集:x_train,y_train\n",
    "# 测试集:x_test,y_test"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "7a39b7d9-9774-463b-97bd-efadb71b2a12",
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.preprocessing import MinMaxScaler\n",
    "mm = MinMaxScaler()\n",
    "# 对训练集数据进行归一化处理\n",
    "m_x_train = mm.fit_transform(x_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "e6d21f96-a5c6-4a5d-90a7-5cb89c808f47",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 使用训练集数据训练模型\n",
    "# 使用m_x_train和y_train训练模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "9aa8194a-7a04-4937-a600-1337007625d3",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 保存mm对象\n",
    "import pickle\n",
    "with open('./mm.pkl','wb') as fp:\n",
    "    pickle.dump(mm,fp)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "8fe52270-02df-4919-b769-c34f930d6975",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 读取对象\n",
    "with open('./mm.pkl','rb') as fp:\n",
    "    n_mm=pickle.load(fp)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "2bdb53ca-cf0f-412b-911c-47f1183c1bae",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[ 0.        ,  0.5       ,  0.01754386,  0.04166667],\n",
       "        [ 0.05714286,  0.66666667, -0.03508772,  0.04166667],\n",
       "        [ 0.31428571,  0.16666667,  0.45614035,  0.41666667],\n",
       "        [-0.02857143,  0.41666667, -0.01754386,  0.        ],\n",
       "        [ 0.22857143,  0.58333333,  0.03508772,  0.04166667],\n",
       "        [ 0.2       ,  0.625     ,  0.03508772,  0.04166667],\n",
       "        [ 0.        ,  0.375     ,  0.03508772,  0.04166667],\n",
       "        [ 0.11428571,  0.45833333,  0.07017544,  0.04166667],\n",
       "        [ 0.08571429,  0.5       ,  0.01754386,  0.04166667],\n",
       "        [ 0.17142857,  0.625     ,  0.07017544,  0.20833333],\n",
       "        [ 0.17142857,  0.5       ,  0.        ,  0.04166667],\n",
       "        [ 0.48571429,  0.33333333,  0.61403509,  0.45833333],\n",
       "        [ 0.37142857,  0.20833333,  0.66666667,  0.79166667],\n",
       "        [ 0.57142857,  0.5       ,  0.71929825,  0.91666667],\n",
       "        [ 0.48571429,  0.41666667,  0.59649123,  0.54166667],\n",
       "        [ 0.8       ,  0.5       ,  0.84210526,  0.70833333],\n",
       "        [ 0.37142857,  0.33333333,  0.57894737,  0.5       ],\n",
       "        [ 0.34285714,  0.20833333,  0.47368421,  0.41666667],\n",
       "        [ 0.2       ,  0.54166667,  0.0877193 ,  0.16666667],\n",
       "        [ 0.34285714,  0.41666667,  0.57894737,  0.58333333],\n",
       "        [ 0.42857143,  0.41666667,  0.52631579,  0.58333333],\n",
       "        [ 0.68571429,  0.41666667,  0.75438596,  0.83333333],\n",
       "        [ 0.48571429,  0.25      ,  0.77192982,  0.54166667],\n",
       "        [ 0.17142857,  0.66666667,  0.03508772,  0.04166667],\n",
       "        [ 0.54285714,  0.33333333,  0.68421053,  0.58333333],\n",
       "        [ 0.65714286,  0.45833333,  0.56140351,  0.54166667],\n",
       "        [ 0.57142857,  0.375     ,  0.54385965,  0.5       ],\n",
       "        [ 0.54285714,  0.20833333,  0.64912281,  0.58333333],\n",
       "        [ 0.11428571,  0.41666667,  0.03508772,  0.        ],\n",
       "        [ 0.05714286,  0.58333333,  0.03508772,  0.08333333]]),\n",
       " array([0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 1, 2, 1, 1, 0, 1, 1, 2,\n",
       "        2, 0, 2, 1, 1, 1, 0, 0]))"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#使用该对象对测试集进行归一化处理\n",
    "m_x_test=n_mm.transform(x_test)\n",
    "# 测试模型\n",
    "m_x_test,y_test"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cca26890-8a61-46f2-a0a0-a4bd4edd0a4b",
   "metadata": {},
   "source": [
    "# 机器学习基础\n",
    "- 机器学习算法分类\n",
    "- 机器学习开发流程"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6f31a281-da88-4832-8317-519c09ab425a",
   "metadata": {},
   "source": [
    "- 机器学习最终进行预测出来的结果其实都是通过相关算法计算出来的结果,所以说在机器学习中算法是核心,数据是计算的基础\n",
    "- 找准定位:大部分复杂模型的算法都是算法工程师在做,我们只需要\n",
    "  - 学会分析问题,使用机器学习相关算法完成对应要求\n",
    "  - 掌握算法的基本思想,学会对不同问题选择对应的算法去解决\n",
    "  - 学会利用框架和库解决问题"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5333f488-fc2b-4776-bc9d-702278a3c2af",
   "metadata": {},
   "source": [
    "### 机器学习中的数据类型"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "72f444ec-9226-4e45-8080-73c6329a33bb",
   "metadata": {},
   "source": [
    "- 机器学习中的数据类型分为:\n",
    "  - 离散型数据:\n",
    "    - 取值范围是有限个值或者一个数列构成的,表示分类情况,如:企业数量,产品数量等\n",
    "    - 离散变量则是通过计数方式取得的,即是对所要统计的对象进行计数,增长量非固定的,如:一个地区的企业数目可以是今年只有一家,而第二年开了十家;一个企业的职工人数今年只有10人,第二年一次招聘20人等.\n",
    "  - 连续型数据:\n",
    "    - 连续变量是一直叠加上去的,增长率可以划分为固定的单位,即:1,2,3... 例如:一个人的身高,先涨到1.51,然后涨到1.52,1.53...\n",
    "    - 取值范围是一个区间,它可以在该区间中间取连续值,即连续型变量可以取到区间中的任意值,并且有度量单位.例如:身高,年龄,体重,金额\n",
    "  - 注意:\n",
    "    - 连续型数据的增长是有规律的,离散型数据的增长是无规律的\n",
    "    - 连续型数据是区间可分的,而离散型数据是区间不可分的"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d7513b35-ea2d-48be-b702-0d5363046923",
   "metadata": {},
   "source": [
    "### 机器学习算法分类"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "915a18aa-0af3-4494-8229-63aacb3d3341",
   "metadata": {},
   "source": [
    "- 分类和回归问题\n",
    "  - 分类算法基于的是[标签数据]为[离散数据]\n",
    "  - 回归算法基于的是[标签数据]为[连续数据]\n",
    "  - 结论:在社会中产生的数据必然是离散或者连续的数据,那么针对企业数据所产生的需求也无非是分类问题或者回归问题"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "80935097-7c90-43da-ac2b-4128ca7dd8f0",
   "metadata": {},
   "source": [
    "- 分类问题应用\n",
    "  - 银行业务中,构建客户分类模型,按客户按照贷款风险的大小进行分类\n",
    "  - 图像处理中,分类可以用来检测图像中是否有人脸出现,动物类别\n",
    "  - 手写识别中,分类可以用于识别手写数据\n",
    "  - ..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a3e47aa2-91ab-4174-83fe-c77d5abf609f",
   "metadata": {},
   "source": [
    "- 回归问题应用\n",
    "  - 房价预测,根据某地历史房价数据,进行一个预测\n",
    "  - 金融信息,每日股票值\n",
    "  - ..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "84f27cfa-fa8d-42ef-b689-4e405ac9450e",
   "metadata": {},
   "source": [
    "### 机器学习开发流程"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a6e4bb9b-ebba-4ce4-a335-e39c2d58fc61",
   "metadata": {},
   "source": [
    "- 1.数据采集\n",
    "  - 公司内部产生的数据\n",
    "  - 和其他公司合作获取的数据\n",
    "  - 购买的数据\n",
    "- 2.分类数据所对应要解决需求或者问题是什么,根据目标数据推断问题属于回归还是分类\n",
    "- 3.数据的基本清洗\n",
    "  - 数据清洗\n",
    "  - 合并\n",
    "  - 级联等\n",
    "- 4.特征工程:对特征进行处理\n",
    "  - 特征抽取\n",
    "  - 特征预处理\n",
    "  - 降维等\n",
    "- 5.选择合适的模型,然后对其进行训练\n",
    "- 6.模型的评估\n",
    "- 7.上线使用"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
